﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MSWord = Microsoft.Office.Interop.Word;


namespace UseMicrosoftOfficeInteropWord
{
    class Program
    {
        //由于使用的是COM库，因此有许多变量需要用Missing.Value代替
        static Object Nothing = Missing.Value;

        static object unite = MSWord.WdUnits.wdStory;
        static object extend = MSWord.WdMovementType.wdExtend;

        static string imagePath = Environment.CurrentDirectory + "\\Files\\image.jpg";

        static void Main(string[] args)
        {
            //添加引用COM里面的 Microsoft Word 12.0 Object. Library 引用（12.0表示Word 2007版本）
            //把引用中的Microsoft.Office.Interop.Word的“属性”中的嵌入互操作设为False

            //初始化
            MSWord.Application wordApp = new MSWord.ApplicationClass();
            //使文档可见
            wordApp.Visible = true;

            //Word文档变量
            MSWord.Document wordDoc = wordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);

            //页面设置
            SetPage(wordApp, wordDoc);

            //页眉设置
            SetPageHeader(wordApp, wordDoc);

            //页码设置
            SetPageNumbers(wordApp, wordDoc);

            //插入文本
            InsertText(wordApp, wordDoc);

            //插入图片
            InsertImage(wordApp, wordDoc);

            //插入表格
            InsertTable(wordApp, wordDoc);

            //保存路径
            object path = Path.Combine(Path.GetFullPath("../../"), "Temp", $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.docx");
            //Word保存格式 https://docs.microsoft.com/zh-cn/office/vba/api/word.wdsaveformat
            object format = MSWord.WdSaveFormat.wdFormatDocumentDefault;
            //word保存方法
            wordDoc.SaveAs(ref path, ref format, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);

            //看是不是要打印
            //wordDoc.PrintOut();

            wordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
            //关闭wordApp组件对象
            wordApp.Quit(ref Nothing, ref Nothing, ref Nothing);

            //我还要打开这个文档玩玩
            MSWord.Application app = new MSWord.Application();
            MSWord.Document doc = null;
            try
            {

                object unknow = Type.Missing;
                app.Visible = false;//文档不可见
                doc = app.Documents.Open(ref path,
                    ref unknow, ref unknow, ref unknow, ref unknow,
                    ref unknow, ref unknow, ref unknow, ref unknow,
                    ref unknow, ref unknow, ref unknow, ref unknow,
                    ref unknow, ref unknow, ref unknow);
                //获取第一段段落文字
                string temp = doc.Paragraphs[1].Range.Text.Trim();

                //获取第一个表格某个单元格文字
                temp = doc.Tables[1].Cell(1, 1).Range.Text;

                //获取文档内嵌资源，坐标1开始
                MSWord.InlineShape shape = doc.InlineShapes[1];
                //判断是否为图片
                if (shape.Type == MSWord.WdInlineShapeType.wdInlineShapePicture)
                {
                    // 获取Word中的图片

                    //通过byte的方式来实现图片的提取会导致提取出来的图片的质量严重下降
                    byte[] img = (byte[])shape.Range.EnhMetaFileBits;
                    Bitmap bmp = new Bitmap(new MemoryStream(img));
                    //bmp.Save("图片地址.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

                    //利用剪贴板保存数据
                    shape.Select();//选定当前图片
                    doc.ActiveWindow.Selection.Copy();//copy当前图片
                    if (Clipboard.ContainsImage())
                    {
                        bmp = new Bitmap(Clipboard.GetImage());
                        string imgName = shape.ToString();
                        //bmp.Save("图片地址.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                    }
                }

            }
            catch (Exception ex)
            {
                //Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 页面设置
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void SetPage(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            //页面设置
            wordDoc.PageSetup.PaperSize = MSWord.WdPaperSize.wdPaperA4;//设置纸张样式为A4纸 https://docs.microsoft.com/zh-cn/office/vba/api/word.wdpapersize
            wordDoc.PageSetup.Orientation = MSWord.WdOrientation.wdOrientPortrait;//排列方式为垂直方向
            wordDoc.PageSetup.TopMargin = 57.0f;
            wordDoc.PageSetup.BottomMargin = 57.0f;
            wordDoc.PageSetup.LeftMargin = 57.0f;
            wordDoc.PageSetup.RightMargin = 57.0f;
        }

        /// <summary>
        /// 页眉设置
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void SetPageHeader(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            wordDoc.PageSetup.HeaderDistance = 30.0f;//页眉位置

            //设置页眉
            wordApp.ActiveWindow.View.Type = MSWord.WdViewType.wdPrintView;//页面视图样式 https://docs.microsoft.com/zh-cn/office/vba/api/word.wdviewtype
            wordApp.ActiveWindow.View.SeekView = MSWord.WdSeekView.wdSeekPrimaryHeader;//进入页眉设置，其中页眉边距在页面设置中已完成
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphRight;//页眉中的文字右对齐


            //插入页眉图片(测试结果图片未插入成功)
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;
            MSWord.InlineShape shape1 = wordApp.ActiveWindow.ActivePane.Selection.InlineShapes.AddPicture(imagePath, ref Nothing, ref Nothing, ref Nothing);
            shape1.Height = 5;//强行设置貌似无效，图片没有按设置的缩放——图片的比例并没有改变。
            shape1.Width = 20;
            wordApp.ActiveWindow.ActivePane.Selection.InsertAfter("  文档页眉");//在页眉的图片后面追加几个字

            //去掉页眉的横线
            wordApp.ActiveWindow.ActivePane.Selection.ParagraphFormat.Borders[MSWord.WdBorderType.wdBorderBottom].LineStyle = MSWord.WdLineStyle.wdLineStyleNone;
            wordApp.ActiveWindow.ActivePane.Selection.Borders[MSWord.WdBorderType.wdBorderBottom].Visible = false;
            wordApp.ActiveWindow.ActivePane.View.SeekView = MSWord.WdSeekView.wdSeekMainDocument;//退出页眉设置
        }

        /// <summary>
        /// 页码设置
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void SetPageNumbers(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            //为当前页添加页码
            MSWord.PageNumbers pns = wordApp.Selection.Sections[1].Headers[MSWord.WdHeaderFooterIndex.wdHeaderFooterEvenPages].PageNumbers;//获取当前页的号码
            pns.NumberStyle = MSWord.WdPageNumberStyle.wdPageNumberStyleNumberInDash;//设置页码的风格，是Dash形还是圆形的
            pns.HeadingLevelForChapter = 0;
            pns.IncludeChapterNumber = false;
            pns.RestartNumberingAtSection = false;
            pns.StartingNumber = 0; //开始页页码？
            object pagenmbetal = MSWord.WdPageNumberAlignment.wdAlignPageNumberCenter;//将号码设置在中间
            object first = true;
            wordApp.Selection.Sections[1].Footers[MSWord.WdHeaderFooterIndex.wdHeaderFooterEvenPages].PageNumbers.Add(ref pagenmbetal, ref first);
        }

        /// <summary>
        /// 插入文本
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void InsertText(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            InitFont(wordApp, wordDoc);//初始化字体样式

            wordDoc.Paragraphs.Last.Range.Text += "+=先换行在添加文字";

            wordDoc.Paragraphs.Last.Range.Text = "加\\n换行\n";

            wordDoc.Paragraphs.Last.Range.Text = "不加'\\n'或+=直接覆盖";

            wordDoc.Paragraphs.Last.Range.InsertAfter("，追加到末尾");

            //添加到新段落
            wordDoc.Paragraphs.Add(ref Nothing);

            //将文档的前4个字替换成"哥是替换文字"，并将其颜色设为红粗体
            object start = 0;
            object end = 4;
            MSWord.Range rang = wordDoc.Range(ref start, ref end);
            rang.Font.Color = MSWord.WdColor.wdColorRed;
            rang.Font.Bold = 1;
            rang.Text = "哥是替换文字";
            wordDoc.Range(ref start, ref end);

            //插入文本
            wordDoc.Paragraphs.Add(ref Nothing);
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾
            wordApp.Selection.ParagraphFormat.FirstLineIndent = 30;//取消首行缩进的长度
            wordDoc.Paragraphs.Last.Range.Font.Size = 15;
            wordDoc.Paragraphs.Last.Range.Font.Name = "黑体";
            wordDoc.Paragraphs.Last.Range.Font.Bold = 1;
            wordDoc.Paragraphs.Last.Range.Font.Italic = 1;
            wordDoc.Paragraphs.Last.Range.Font.Color = MSWord.WdColor.wdColorBlue;
            wordDoc.Paragraphs.Last.Range.Font.Underline = MSWord.WdUnderline.wdUnderlineDashHeavy;//下划线样式
            wordDoc.Paragraphs.Last.Range.Font.UnderlineColor = MSWord.WdColor.wdColorRed;//下划线颜色
            wordDoc.Paragraphs.Last.Range.Text = "15号黑体加粗倾斜蓝色字体，红色下划线";

            //部分设置
            wordDoc.Paragraphs.Add(ref Nothing);//换个段落
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾
            wordApp.Selection.EndKey(ref unite, ref extend);//将光标移到文本末尾并选中
            InitFont(wordApp, wordDoc);//初始化字体样式
            wordApp.Selection.Text = "部分";
            wordApp.Selection.Font.Bold = 0;
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾
            wordApp.Selection.EndKey(ref unite, ref extend);//将光标移到文本末尾并选中
            wordApp.Selection.Text = "粗体";
            wordApp.Selection.Font.Bold = 1;
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾
            wordApp.Selection.EndKey(ref unite, ref extend);//将光标移到文本末尾并选中
            wordApp.Selection.Text = "显示";
            wordApp.Selection.Font.Bold = 0;
        }

        /// <summary>
        /// 初始化字体设置
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void InitFont(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            //设置文档的行间距
            wordApp.Selection.ParagraphFormat.LineSpacing = 16f;
            //首行缩进的长度
            wordApp.Selection.ParagraphFormat.FirstLineIndent = 0;
            //字体大小
            wordDoc.Paragraphs.Last.Range.Font.Size = 12;
            //字体名称
            wordDoc.Paragraphs.Last.Range.Font.Name = "黑体";
            //加粗
            wordDoc.Paragraphs.Last.Range.Font.Bold = 0;
            //倾斜
            wordDoc.Paragraphs.Last.Range.Font.Italic = 0;
            //颜色
            wordDoc.Paragraphs.Last.Range.Font.Color = MSWord.WdColor.wdColorBlack;
            //下划线样式
            wordDoc.Paragraphs.Last.Range.Font.Underline = MSWord.WdUnderline.wdUnderlineNone;
            //下划线颜色
            wordDoc.Paragraphs.Last.Range.Font.UnderlineColor = MSWord.WdColor.wdColorBlack;
        }

        /// <summary>
        /// 插入图片
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void InsertImage(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            wordDoc.Paragraphs.Add(ref Nothing);
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾

            //要向Word文档中插入图片的位置
            Object range = wordDoc.Paragraphs.Last.Range;
            //定义该插入的图片是否为外部链接
            Object linkToFile = false;//默认,这里貌似设置为bool类型更清晰一些
            //定义要插入的图片是否随Word文档一起保存
            Object saveWithDocument = true;//默认
            //使用InlineShapes.AddPicture方法(【即“嵌入型”】)插入图片
            wordDoc.InlineShapes.AddPicture(imagePath, ref linkToFile, ref saveWithDocument, ref range);
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;//居中显示图片

            //设置图片宽高的绝对大小

            //wordDoc.InlineShapes[1].Width = 200;
            //wordDoc.InlineShapes[1].Height = 150;
            //按比例缩放大小

            wordDoc.InlineShapes[1].ScaleWidth = 20;//缩小到20% ？
            wordDoc.InlineShapes[1].ScaleHeight = 20;

            //在图下方居中添加图片标题

            wordDoc.Content.InsertAfter("\n");//换行
            wordApp.Selection.EndKey(ref unite, ref Nothing);
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;//居中
            wordApp.Selection.Font.Size = 10;//字体大小
            wordApp.Selection.TypeText("图1 测试图片\n");
        }

        /// <summary>
        /// 插入表格
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        static void InsertTable(MSWord.Application wordApp, MSWord.Document wordDoc)
        {
            wordDoc.Paragraphs.Add(ref Nothing);
            wordApp.Selection.EndKey(ref unite, ref Nothing);//将光标移到文本末尾
            InitFont(wordApp, wordDoc);//初始化字体样式

            //设置表格的行数和列数
            int tableRow = 6;
            int tableColumn = 6;

            //定义一个Word中的表格对象
            MSWord.Table table = wordDoc.Tables.Add(wordApp.Selection.Range, tableRow, tableColumn, ref Nothing, ref Nothing);

            //默认创建的表格没有边框，这里修改其属性，使得创建的表格带有边框 
            table.Borders.Enable = 1;//这个值可以设置得很大，例如5、13等等

            //从文档表格集合获取表格对象，表格的索引是从1开始的。
            //wordDoc.Tables[1].Cell(1, 1).Range.Text = "列\n行";

            //推荐直接使用表格对象操作
            table.Cell(1, 1).Range.Text = "列\n行";

            //插入表格数据
            for (int i = 1; i < tableRow; i++)
            {
                for (int j = 1; j < tableColumn; j++)
                {
                    if (i == 1)
                    {
                        table.Cell(i, j + 1).Range.Text = "Column " + j;//填充每列的标题
                    }
                    if (j == 1)
                    {
                        table.Cell(i + 1, j).Range.Text = "Row " + i; //填充每行的标题
                    }
                    table.Cell(i + 1, j + 1).Range.Text = i + "行 " + j + "列";  //填充表格的各个小格子
                }
            }

            //添加行
            table.Rows.Add(ref Nothing);
            table.Rows[tableRow + 1].Height = 35;//设置新增加的这行表格的高度
            //向新添加的行的单元格中添加图片
            string FileName = imagePath;//图片所在路径
            object LinkToFile = false;
            object SaveWithDocument = true;
            object Anchor = table.Cell(tableRow + 1, tableColumn).Range;//选中要添加图片的单元格
            wordDoc.Application.ActiveDocument.InlineShapes.AddPicture(FileName, ref LinkToFile, ref SaveWithDocument, ref Anchor);

            //由于是本文档的第2张图，所以这里是InlineShapes[2]
            wordDoc.Application.ActiveDocument.InlineShapes[2].Width = 50;//图片宽度
            wordDoc.Application.ActiveDocument.InlineShapes[2].Height = 35;//图片高度

            // 将图片设置为四周环绕型
            MSWord.Shape s = wordDoc.Application.ActiveDocument.InlineShapes[2].ConvertToShape();
            s.WrapFormat.Type = MSWord.WdWrapType.wdWrapSquare;


            //设置table样式
            table.Rows.HeightRule = MSWord.WdRowHeightRule.wdRowHeightAtLeast;//高度规则是：行高有最低值下限？
            table.Rows.Height = wordApp.CentimetersToPoints(float.Parse("0.8"));// 

            table.Range.Font.Size = 10.5F;
            table.Range.Font.Bold = 0;

            table.Range.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;//表格文本居中
            table.Range.Cells.VerticalAlignment = MSWord.WdCellVerticalAlignment.wdCellAlignVerticalBottom;//文本垂直贴到底部
            //设置table边框样式
            table.Borders.OutsideLineStyle = MSWord.WdLineStyle.wdLineStyleDouble;//表格外框是双线
            table.Borders.InsideLineStyle = MSWord.WdLineStyle.wdLineStyleSingle;//表格内框是单线

            table.Rows[1].Range.Font.Bold = 1;//加粗
            table.Rows[1].Range.Font.Size = 12F;
            table.Cell(1, 1).Range.Font.Size = 10.5F;
            wordApp.Selection.Cells.Height = 30;//所有单元格的高度

            //除第一行外，其他行的行高都设置为20
            for (int i = 2; i <= tableRow; i++)
            {
                table.Rows[i].Height = 20;
            }

            //将表格左上角的单元格里的文字（“行” 和 “列”）居右
            table.Cell(1, 1).Range.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphRight;
            //将表格左上角的单元格里面下面的“列”字移到左边，相比上一行就是将ParagraphFormat改成了Paragraphs[2].Format
            table.Cell(1, 1).Range.Paragraphs[2].Format.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphLeft;

            table.Columns[1].Width = 50;//将第 1列宽度设置为50

            //将其他列的宽度都设置为75
            for (int i = 2; i <= tableColumn; i++)
            {
                table.Columns[i].Width = 75;
            }


            //添加表头斜线,并设置表头的样式
            table.Cell(1, 1).Borders[MSWord.WdBorderType.wdBorderDiagonalDown].Visible = true;
            table.Cell(1, 1).Borders[MSWord.WdBorderType.wdBorderDiagonalDown].Color = MSWord.WdColor.wdColorRed;
            table.Cell(1, 1).Borders[MSWord.WdBorderType.wdBorderDiagonalDown].LineWidth = MSWord.WdLineWidth.wdLineWidth150pt;

            //合并单元格

            //合并后只有(4,4)坐标，其他合并的坐标会为空值,例如（4.5）会报集合不存在
            table.Cell(4, 4).Merge(table.Cell(4, 5));//横向合并

            table.Cell(2, 3).Merge(table.Cell(4, 3));//纵向合并，合并(2,3),(3,3),(4,3)

            table.Cell(2, 2).Select();//选择某行单元格

            wordApp.Selection.StartOf();//光标指向单元格开始处
        }
    }
}
